/*
 *   Copyright (C)  2016 android@19code.com
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package com.jevons.muffin.util;

import android.Manifest;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import android.webkit.WebView;

import androidx.core.content.ContextCompat;

import com.jevons.muffin.utilcode.LogUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;

import static android.Manifest.permission.READ_PHONE_STATE;

/**
 * 手机操作工具类
 * create at:  2016/8/119
 */
public final class DeviceUtils {

    private static final String TAG = DeviceUtils.class.getSimpleName();

    /**
     * 获取AndroidId
     *
     * @param ctx Context
     * @return String
     */
    public static String getAndroidID(Context ctx) {
        return Settings.Secure.getString(ctx.getContentResolver(), Settings.Secure.ANDROID_ID);
    }

    /**
     * 获取手机IMEI
     *
     * @param mContext Context
     * @return String IMEI
     */
    public static String getIMEI(Context mContext) {

        //查看权限
        boolean permissionCheck = ContextCompat.checkSelfPermission(mContext, READ_PHONE_STATE) ==
                PackageManager.PERMISSION_GRANTED;
        if (!permissionCheck) {
            return "000000000000000";
        }
        String deviceId = ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();

        if (!TextUtils.isEmpty(deviceId)) {
            if (deviceId.length() > 15) {
                deviceId = deviceId.substring(0, 15);
            }
            return deviceId;
        }
        return "000000000000000";
    }

    /**
     * 获取手机IMSI
     *
     * @param ctx Context
     * @return String
     */
    public static String getIMSI(Context ctx) {
        TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
        boolean permissionCheck = ContextCompat.checkSelfPermission(ctx, READ_PHONE_STATE) ==
                PackageManager.PERMISSION_GRANTED;
        if (!permissionCheck) {
            return null;
        }
        return tm.getSubscriberId() != null ? tm.getSubscriberId() : null;
    }

    /**
     * 获取wifi-mac地址
     *
     * @param ctx Context
     * @return String
     */
    public static String getWifiMacAddr(Context ctx) {
        return NetUtils.getWifiMacAddr(ctx);
    }

    /**
     * 获取手机IP地址
     *
     * @param ctx Context
     * @return String Ip地址
     */
    public static String getIP(Context ctx) {
        WifiManager wifiManager = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE);
        return wifiManager.isWifiEnabled() ? getWifiIP(wifiManager) : getGPRSIP();
    }

    /**
     * 获取Wifi-IP
     *
     * @param wifiManager WifiManager
     * @return String wifi-ip地址
     */
    public static String getWifiIP(WifiManager wifiManager) {
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        String ip = intToIp(wifiInfo.getIpAddress());
        return ip != null ? ip : "";
    }

    /**
     * 获取手机GRPS(用流量时)的Ip
     *
     * @return GPRS-ip地址
     */
    public static String getGPRSIP() {
        String ip = null;
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                for (Enumeration<InetAddress> enumIpAddr = en.nextElement().getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        ip = inetAddress.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            ip = null;
            LogUtils.printWarnTag(TAG, e.toString());
        }
        return ip;
    }

    /**
     * 把int类型转化为ip地址
     *
     * @param i int数值
     * @return String ip地址
     */
    private static String intToIp(int i) {
        return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + (i >> 24 & 0xFF);
    }

    /**
     * 获取手机的唯一标识
     *
     * @return String  Build.SERIAL
     */
    public static String getSerial() {
        return Build.SERIAL;
    }

    /**
     * 获取SIM卡的唯一标识
     *
     * @param ctx Context
     * @return String SIM-Serial
     */
    public static String getSIMSerial(Context ctx) {
        boolean permissionCheck = ContextCompat.checkSelfPermission(ctx, READ_PHONE_STATE) ==
                PackageManager.PERMISSION_GRANTED;
        if (!permissionCheck) {
            return null;
        }
        TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getSimSerialNumber();
    }

    /**
     * 获取手机号码
     *
     * @param ctx Context
     * @return String 手机号码
     */
    public static String getPhoneNumber(Context ctx) {
        boolean permissionCheck = ContextCompat.checkSelfPermission(ctx, READ_PHONE_STATE) ==
                PackageManager.PERMISSION_GRANTED;
        if (!permissionCheck) {
            return null;
        }
        TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getLine1Number();
    }

    /**
     * 获取运营商网络代码（Mobile Network Code）
     *
     * @param ctx Context
     * @return String 运营商网络标识码
     */
    public static String getMNC(Context ctx) {
        String providersName = "";
        TelephonyManager telephonyManager = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
        if (telephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY) {
            providersName = telephonyManager.getSimOperator();
            providersName = providersName == null ? "" : providersName;
        }
        return providersName;
    }

    /**
     * 获取运营商的名称
     *
     * @param ctx Context
     * @return String 运营商名称 （如:china mobile）
     */
    public static String getCarrier(Context ctx) {
        TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getNetworkOperatorName().toLowerCase(Locale.getDefault());
    }

    /**
     * 根据imsi获取手机运营商的名称
     *
     * @param imsi imsi字符串
     * @return String 运营商名称
     */
    public static String getCarrierByIMSI(String imsi) {
        if (imsi != null) {
            if ((imsi.startsWith("46000")) || (imsi.startsWith("46002")) || (imsi.startsWith("46007"))
                    || (imsi.startsWith("46020"))) {
                return "中国移动";
            }
            if (imsi.startsWith("46001")) {
                return "中国联通";
            }
            if ((imsi.startsWith("46003")) || (imsi.startsWith("46005"))) {
                return "中国电信";
            }
        }
        return "--";
    }

    /**
     * 获取手机型号
     *
     * @return String 手机型号
     */
    public static String getModel() {
        return Build.MODEL;
    }

    /**
     * 获取手机品牌
     *
     * @return String 手机品牌
     */
    public static String getBuildBrand() {
        return Build.BRAND;
    }

    /**
     * 获取设备主机地址
     *
     * @return String Build.HOST
     */
    public static String getBuildHost() {
        return Build.HOST;
    }

    /**
     * 获取描述Build的标签
     *
     * @return String Build.TAGS
     */
    public static String getBuildTags() {
        return Build.TAGS;
    }

    /**
     * 获取设备固件版本推出的日期
     *
     * @return String Build.TIME
     */
    public static long getBuildTime() {
        return Build.TIME;
    }

    /**
     * 设备用户名 基本上都为android-build
     *
     * @return String Build.USER
     */
    public static String getBuildUser() {
        return Build.USER;
    }

    /**
     * 获取手机版本
     *
     * @return String 手机版本
     */
    public static String getBuildVersion() {
        return Build.VERSION.RELEASE;
    }

    /**
     * 设备当前的系统开发代号，一般使用REL代替
     *
     * @return String Build.VERSION.CODENAME
     */
    public static String getBuildVersionCodename() {
        return Build.VERSION.CODENAME;
    }

    /**
     * 获取源码控制版本号
     *
     * @return String Build.VERSION.INCREMENTAL
     */
    public static String getBuildVersionIncremental() {
        return Build.VERSION.INCREMENTAL;
    }

    /**
     * 系统的API级别 一般使用下面大的SDK_INT 来查看
     *
     * @return String Build.VERSION.SDK_INT
     */
    public static int getBuildVersionSDK() {
        return Build.VERSION.SDK_INT;
    }

    /**
     * 设备版本号
     *
     * @return Build.ID
     */
    public static String getBuildID() {
        return Build.ID;
    }

    /**
     * 获取设备制造商
     *
     * @return String Build.MANUFACTURER
     */
    public static String getManufacturer() {
        return Build.MANUFACTURER;
    }

    /**
     * 获取系统启动程序版本号
     *
     * @return String Build.BOOTLOADER
     */
    public static String getBootloader() {
        return Build.BOOTLOADER;
    }

    /**
     * 获取设备显示的版本包（在系统设置中显示为版本号）和ID一样
     *
     * @return String Build.DISPLAY
     */
    public static String getDisplayVersion() {
        return Build.DISPLAY;
    }

    /**
     * 设备的唯一标识。由设备的多个信息拼接合成。
     *
     * @return String Build.FINGERPRINT
     */
    public static String getFingerprint() {
        return Build.FINGERPRINT;
    }

    /**
     * 设备硬件名称,一般和基板名称一样（BOARD）
     *
     * @return String Build.HARDWARE
     */
    public static String getHardware() {
        return Build.HARDWARE;
    }

    /**
     * 整个产品的名称
     *
     * @return String Build.PRODUCT
     */
    public static String getProduct() {
        return Build.PRODUCT;
    }

    /**
     * 获取设备驱动名称
     *
     * @return String Build.DEVICE
     */
    public static String getDevice() {
        return Build.DEVICE;
    }

    /**
     * 获取设备基板名称
     *
     * @return String Build.BOARD
     */
    public static String getBoard() {
        return Build.BOARD;
    }

    /**
     * 获取广播版本
     *
     * @return String
     */
    public static String getRadioVersion() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH ? Build.getRadioVersion() : "";
    }

    /**
     * CPU指令集
     *
     * @return String[]
     */
    public static String[] getSupportedABIS() {
        String[] result = new String[]{"-"};
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            result = Build.SUPPORTED_ABIS;
        }
        if (result == null || result.length == 0) {
            result = new String[]{"-"};
        }
        return result;
    }

    /**
     * 获取CPU的信息
     *
     * @return cpuInfo[0]-型号 ----cpuInfo[1]频率
     */
    public static String[] getCpuInfo() {

        String fileName = "/proc/cpuinfo";
        String temp;
        String[] cpuInfo = {"", ""}; // 1-cpu型号 //2-cpu频率
        String[] strs;
        try {
            FileReader fr = new FileReader(fileName);
            BufferedReader reader = new BufferedReader(fr, 8192);
            temp = reader.readLine();
            strs = temp.split("\\s+");
            for (int i = 2; i < strs.length; i++) {
                cpuInfo[0] = cpuInfo[0] + strs[i] + " ";
            }
            temp = reader.readLine();
            strs = temp.split("\\s+");
            cpuInfo[1] += strs[2];
            reader.close();
        } catch (IOException e) {
            Log.e("DeviceUtils", e.toString());
        }

        return cpuInfo;
    }

    /**
     * 获取手机核心数
     *
     * @return 核心数
     */
    public static int getNumCores() {
        try {
            File dir = new File("/sys/devices/system/cpu/");
            File[] files = dir.listFiles(new FileFilter() {

                @Override
                public boolean accept(File pathname) {
                    return Pattern.matches("cpu[0-9]", pathname.getName());
                }

            });
            return files.length;
        } catch (Exception e) {
            LogUtils.printWarnTag(TAG, e.toString());
            return 1;
        }
    }

    public static String getScreenDisplayID(Context ctx) {
        WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
        return String.valueOf(wm.getDefaultDisplay().getDisplayId());
    }

    /**
     * 获取默认的语言类型
     *
     * @return String  Locale.getDefault().getLanguage()
     */
    public static String getLanguage() {
        return Locale.getDefault().getLanguage();
    }

    /**
     * 获取手机所在的国家
     *
     * @param ctx Context
     * @return String
     */
    public static String getCountry(Context ctx) {
        TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
        Locale locale = Locale.getDefault();
        return tm.getSimState() == TelephonyManager.SIM_STATE_READY ? tm.getSimCountryIso().toLowerCase(Locale.getDefault()) : locale.getCountry().toLowerCase(locale);
    }

    /**
     * 获取手机device id (Device ID是Android用户在Google认证过手机的设备唯一标识,国内很多手机没有认证，多以没有)
     * Google service framework
     * <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
     *
     * @param context Context
     * @return String 手机device id
     */
    public static String getGSFID(Context context) {
        String result;
        final Uri URI = Uri.parse("content://com.google.android.gsf.gservices");
        final String ID_KEY = "android_id";
        String[] params = {ID_KEY};
        Cursor c = context.getContentResolver().query(URI, null, null, params, null);
        if (c == null || !c.moveToFirst() || c.getColumnCount() < 2) {
            return null;
        } else {
            result = Long.toHexString(Long.parseLong(c.getString(1)));
        }
        c.close();
        return result;
    }

    /**
     * 获取蓝牙的Mac地址
     * <uses-permission android:name="android.permission.BLUETOOTH"/>
     *
     * @param context Context
     * @return String 蓝牙的mac地址
     */
    public static String getBluetoothMAC(Context context) {
        String result = null;
        try {
            if (context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH)
                    == PackageManager.PERMISSION_GRANTED) {
                BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
                result = bta.getAddress();
            }
        } catch (Exception e) {
            LogUtils.printWarnTag(TAG, e.toString());
        }
        return result;
    }

    /**
     * 获取蓝牙的状态
     *
     * @return 取值为BluetoothAdapter的四个静态字段：STATE_OFF, STATE_TURNING_OFF, STATE_ON, STATE_TURNING_ON
     * @throws Exception 没有找到蓝牙设备
     */
    public static int getBluetoothState() throws Exception {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            throw new Exception("bluetooth device not found!");
        } else {
            return bluetoothAdapter.getState();
        }
    }

    /**
     * 判断蓝牙是否打开
     *
     * @return true：已经打开或者正在打开；false：已经关闭或者正在关闭
     */
    public static boolean isBluetoothOpen() {
        int bluetoothStateCode = 0;
        try {
            bluetoothStateCode = getBluetoothState();
        } catch (Exception e) {
            LogUtils.printWarnTag(TAG, e.toString());
        }
        return bluetoothStateCode == BluetoothAdapter.STATE_ON ||
                bluetoothStateCode == BluetoothAdapter.STATE_TURNING_ON;
    }

    /**
     * 设置蓝牙状态
     *
     * @param enable 打开
     */
    public static void setBluetooth(boolean enable) {
        //如果当前蓝牙的状态与要设置的状态不一样
        try {
            if (isBluetoothOpen() != enable) {
                //如果是要打开就打开，否则关闭
                if (enable) {
                    BluetoothAdapter.getDefaultAdapter().enable();
                } else {
                    BluetoothAdapter.getDefaultAdapter().disable();
                }
            }
        } catch (Exception e) {
            LogUtils.printWarnTag(TAG, e.toString());
        }
    }

    /**
     * 判断飞行模式是否打开，需要WRITE_APN_SETTINGS权限
     *
     * @param context Context
     * @return true：打开；false：关闭；默认关闭
     */
    public static boolean isAirplaneModeOpen(Context context) {
        return NetUtils.isAirplaneModeOpen(context);
    }

    /**
     * 设置飞行模式的状态
     *
     * @param context 上下文
     * @param enable  飞行模式的状态
     * @return true 设置成功
     */
    public static boolean setAirplaneMode(Context context, boolean enable) {
        return NetUtils.setAirplaneMode(context, enable);
    }

    /**
     * 是否wifi环境
     *
     * @param cxt Context
     * @return true 是wifi环境
     */
    public static boolean isWiFi(Context cxt) {
        return NetUtils.isWiFi(cxt);
    }

    /**
     * 设置wifi状态
     *
     * @param context Context
     * @param enabled true-可用
     */
    public static void setWifiEnabled(Context context, boolean enabled) {
        NetUtils.setWifiEnabled(context, enabled);
    }

    /**
     * Android设备物理唯一标识符
     *
     * @return String  Android设备物理唯一标识符
     */
    public static String getPsuedoUniqueID() {
        String devIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            devIDShort += (Build.SUPPORTED_ABIS[0].length() % 10);
        } else {
            devIDShort += (Build.CPU_ABI.length() % 10);
        }
        devIDShort += (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
        String serial;
        try {
            serial = Build.class.getField("SERIAL").get(null).toString();
            return new UUID(devIDShort.hashCode(), serial.hashCode()).toString();
        } catch (Exception e) {
            serial = "ESYDV000";
        }
        return new UUID(devIDShort.hashCode(), serial.hashCode()).toString();
    }

    /**
     * 获取的浏览器指纹(User-Agent)
     *
     * @param ctx Context
     * @return 浏览器指纹
     */
    public static String getUA(Context ctx) {
        final String system_ua = System.getProperty("http.agent");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            return new WebView(ctx).getSettings().getDefaultUserAgent(ctx) + "__" + system_ua;
        } else {
            return new WebView(ctx).getSettings().getUserAgentString() + "__" + system_ua;
        }
    }

    /**
     * 获取得屏幕密度
     *
     * @param ctx Context
     * @return 屏幕密度
     */
    public static String getDensity(Context ctx) {
        String densityStr = null;
        final int density = ctx.getResources().getDisplayMetrics().densityDpi;
        switch (density) {
            case DisplayMetrics.DENSITY_LOW:
                densityStr = "LDPI";
                break;
            case DisplayMetrics.DENSITY_MEDIUM:
                densityStr = "MDPI";
                break;
            case DisplayMetrics.DENSITY_TV:
                densityStr = "TVDPI";
                break;
            case DisplayMetrics.DENSITY_HIGH:
                densityStr = "HDPI";
                break;
            case DisplayMetrics.DENSITY_XHIGH:
                densityStr = "XHDPI";
                break;
            case DisplayMetrics.DENSITY_400:
                densityStr = "XMHDPI";
                break;
            case DisplayMetrics.DENSITY_XXHIGH:
                densityStr = "XXHDPI";
                break;
            case DisplayMetrics.DENSITY_XXXHIGH:
                densityStr = "XXXHDPI";
                break;
        }
        return densityStr;
    }

    /**
     * 获取屏幕的宽
     *
     * @param c Context
     * @return 屏幕宽度
     */
    public static int getScreenW(Context c) {
        return c.getResources().getDisplayMetrics().widthPixels;
    }

    /**
     * 获取屏幕的高
     *
     * @param c Context
     * @return 屏幕高度
     */
    public static int getScreenH(Context c) {
        return c.getResources().getDisplayMetrics().heightPixels;
    }

    /**
     * 获取手机的真正尺寸高度（包含状态栏）
     *
     * @param context Context
     * @return 真正高度
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    public static int getScreenRealH(Context context) {
        return DensityUtils.getScreenRealH(context);
    }

    /**
     * 获取状态栏高度
     *
     * @param context Context
     * @return int 状态栏的高度
     */
    public static int getStatusBarH(Context context) {
        return DensityUtils.getStatusBarH(context);
    }

    /**
     * 获取标题栏的高度
     *
     * @param c Context
     * @return int 标题栏高度
     */
    public static int getNavigationBarH(Context c) {
        return DensityUtils.getNavigationBarH(c);
    }



    /**
     * 判断当前设备是手机还是平板，代码来自 Google I/O App for Android
     * @param context
     * @return 平板返回 True，手机返回 False
     */
    public static boolean isPad(Context context) {
        return (context.getResources().getConfiguration().screenLayout
                & Configuration.SCREENLAYOUT_SIZE_MASK)
                >= Configuration.SCREENLAYOUT_SIZE_LARGE;
    }

}